package com.storm.classes.loader
{
	import com.storm.classes.pool.Pool;
	
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	
	public class ImageLoader extends EventDispatcher {
		
		private static const LOADER_POOL:Pool = new Pool(Loader);
		
		public function ImageLoader(data:Object = null, loadedHandler:Function = null, sourceField:String = "source", imageField:String = "image") {
			super();
			if (data) {
				if (data is Array) {
					this.loadImages(data as Array, loadedHandler, sourceField, imageField);
				} else {
					if (data[sourceField] is Array) {
						this.loadImageList(data, loadedHandler, sourceField, imageField);
					} else {
						this.loadImage(data, loadedHandler, sourceField, imageField);
					}
				}
			}
		}
		
		protected function processIOError(error:IOErrorEvent):void {
			
		}
		
		private function loadImage(data:Object, loadedHandler:Function = null, sourceField:String = "source", imageField:String = "image"):void {
			
			function loadCompleteHandler(event:Event):void {
				var loaderInfo:LoaderInfo = (event.currentTarget as LoaderInfo);
				if (loaderInfo.content is Bitmap) {
					data[imageField] = (loaderInfo.content as Bitmap).bitmapData;
				} else {
					data[imageField] = loaderInfo.bytes;
				}
				if (loadedHandler === null) {
					dispatchEvent(new Event(Event.COMPLETE));
				} else {
					loadedHandler(data);
				}
				var loader:Loader = loaderInfo.loader;
				loader.unloadAndStop(false);
				loaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function ioErrorHandler(event:IOErrorEvent):void {
				processIOError(event);
				var loaderInfo:LoaderInfo = (event.currentTarget as LoaderInfo);
				var loader:Loader = loaderInfo.loader;
				loaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			var url:String = data[sourceField];
			if (!url || url == "") {
				loadedHandler(data);
				return;
			}
			var loader:Loader = LOADER_POOL.freeItem;
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			loader.load(new URLRequest(url));
		}
		
		private function loadImageIndex(data:Object, index:int, loadedHandler:Function, sourceField:String, images:Array):void {
			
			function loadCompleteHandler(event:Event):void {
				var loaderInfo:LoaderInfo = (event.currentTarget as LoaderInfo);
				if (loaderInfo.content is Bitmap) {
					images[index] = (loaderInfo.content as Bitmap).bitmapData;
				} else {
					images[index] = loaderInfo.bytes;
				}
				if (loadedHandler === null) {
					dispatchEvent(new Event(Event.COMPLETE));
				} else {
					loadedHandler(data);
				}
				var loader:Loader = loaderInfo.loader;
				loader.unloadAndStop(false);
				loaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			function ioErrorHandler(event:IOErrorEvent):void {
				processIOError(event);
				var loaderInfo:LoaderInfo = (event.currentTarget as LoaderInfo);
				var loader:Loader = loaderInfo.loader;
				loaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
				loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				LOADER_POOL.freeItem = loader;
			}
			
			var url:String = data[sourceField][index];
			if (!url || url == "") {
				loadedHandler(data);
				return;
			}
			var loader:Loader = LOADER_POOL.freeItem;
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
			loader.load(new URLRequest(url));
		}
		
		private function loadImages(datas:Array, loadedHandler:Function = null, sourceField:String = "source", imageField:String = "image"):void {
			var count:int = datas.length;
			for each (var data:Object in datas) {
				this.loadImage(data, function(data:Object):void {
					count --;
					if (count == 0) {
						if (loadedHandler === null) {
							dispatchEvent(new Event(Event.COMPLETE));
						} else {
							loadedHandler(datas);
						}
					}
				}, sourceField, imageField);
			}
		}
		
		private function loadImageList(data:Object, loadedHandler:Function = null, sourceField:String = "source", imageField:String = "image"):void {
			var datas:Array = data[sourceField] as Array;
			
			var count:int = datas.length;
			var images:Array = [];
			for (var i:int = 0; i < count; i++) {
				this.loadImageIndex(data, i, function(data:Object):void {
					count --;
					if (count == 0) {
						data[imageField] = images;
						if (loadedHandler === null) {
							dispatchEvent(new Event(Event.COMPLETE));
						} else {
							loadedHandler(data);
						}
					}
				}, sourceField, images);
			}
		}
	}
}